package workflow

import (
	"encoding/json"
	"project-info/src/constants"
	"project-info/src/handle/common"
	"project-info/src/handle/response"
	"project-info/src/lib"
	"project-info/src/model"
	"project-info/src/service"
	"slices"
)

// FindStartByMyself 获取由我开启的工作流
func FindStartByMyself(c *lib.GinContext) error {
	var req StartByMySelfReq
	if err := c.Bind(&req); err != nil {
		c.Logger().Error("参数错误：" + err.Error())
		return response.JsonFail(c, "参数错误")
	}

	token := lib.JwtParse(c)
	start, end := lib.Paging(req.Page, req.Size)

	var workflowInstances []model.WorkflowInstance
	var total int64
	db := model.DB().Model(&model.WorkflowInstance{}).Where("deleted = 0 and creator_id = ?", token.UserId)
	if req.WorkflowName != "" {
		db = db.Where("workflow_name like ?", "%"+req.WorkflowName+"%")
	}

	if req.Status != "" {
		db = db.Where("status = ?", req.Status)
	}

	if req.Priority != nil {
		db = db.Where("priority = ?", req.Priority)
	}
	if req.CreateStartDate != "" {
		db = db.Where("create_time >= ?", req.CreateStartDate+" 00:00:00")
	}
	if req.CreateEndDate != "" {
		db = db.Where("create_time <= ?", req.CreateEndDate+" 23:59:59")
	}
	db.Count(&total).Order("id desc").Offset(start).Limit(end).Find(&workflowInstances)
	return response.JsonOk(c, map[string]interface{}{"records": workflowInstances, "total": total}, "获取成功")
}

// FindPenddingApprove 查找需要我审批的工作流
func FindPenddingApprove(c *lib.GinContext) error {
	var req *FindPenddingApproveReq
	if err := c.Bind(&req); err != nil {
		c.Logger().Error("参数错误：" + err.Error())
		return response.JsonFail(c, "参数错误")
	}

	token := lib.JwtParse(c)
	start, end := lib.Paging(req.Page, req.Size)

	roleIds, err := service.GetRoleIdsByUserId(c, token.UserId)
	if err != nil {
		c.Logger().Error(err.Error())
		return response.JsonFail(c, "获取角色失败")
	}

	// 通过用户和角色查询有哪些工作流实例id要我审批的,再通过工作流实例id查询工作流实例,避免join导致的重复实例出现
	var nodeAssigneeWorkInstanceIds []int64
	model.DB().Model(&model.NodeAssignee{}).Select("workflow_instance_id").Where("(target_id = ? and type = ?) or (target_id in ? and type = ?)", token.UserId, constants.NodeAssigneeTypeUser, roleIds, constants.NodeAssigneeTypeRole).Find(&nodeAssigneeWorkInstanceIds)

	if len(nodeAssigneeWorkInstanceIds) == 0 {
		return response.JsonOk(c, map[string]interface{}{"records": []model.WorkflowInstance{}, "total": 0}, "获取成功")
	}

	var workflowInstances []model.WorkflowInstance
	var total int64
	db := model.DB().Model(&model.WorkflowInstance{}).Where("id in (?) and workflow_instances.deleted = 0", nodeAssigneeWorkInstanceIds)
	if req.WorkflowName != "" {
		db = db.Where("workflow_name like ?", "%"+req.WorkflowName+"%")
	}
	if req.Creator != "" {
		db = db.Where("creator like ?", "%"+req.Creator+"%")
	}
	if req.Priority != nil {
		db = db.Where("priority = ?", req.Priority)
	}
	db.Count(&total).Order("priority desc, id asc").Offset(start).Limit(end).Find(&workflowInstances)

	return response.JsonOk(c, map[string]interface{}{"records": workflowInstances, "total": total}, "获取成功")
}

// 查询我审批过的工作流实例
func FindApprovedByMyself(c *lib.GinContext) error {
	var req *FindApproveByMyselfReq
	if err := c.Bind(&req); err != nil {
		c.Logger().Error("参数错误：" + err.Error())
		return response.JsonFail(c, "参数错误")
	}

	token := lib.JwtParse(c)
	start, end := lib.Paging(req.Page, req.Size)

	// 通过用户查询有哪些工作流实例id是我审批的,再通过工作流实例id查询工作流实例,避免join导致的重复实例出现
	var nodeOperatorWorkInstanceIds []int64
	operatorDb := model.DB().Model(&model.NodeOperator{}).Where("operator_id = ?", token.UserId)
	if req.ApprovalStartDate != "" {
		// 前端传递格式是yyyy-MM-dd,后端需要转换为yyyy-MM-dd 00:00:00的golang时间类型
		operatorDb = operatorDb.Where("create_time >= ?", req.ApprovalStartDate+" 00:00:00")
	}
	if req.ApprovalEndDate != "" {
		// 前端传递格式是yyyy-MM-dd,后端需要转换为yyyy-MM-dd 23:59:59的golang时间类型
		operatorDb = operatorDb.Where("create_time <= ?", req.ApprovalEndDate+" 23:59:59")
	}
	operatorDb.Select("distinct workflow_instance_id").Find(&nodeOperatorWorkInstanceIds)
	if len(nodeOperatorWorkInstanceIds) == 0 {
		return response.JsonOk(c, map[string]interface{}{"records": []model.WorkflowInstance{}, "total": 0}, "获取成功")
	}

	var workflowInstances []model.WorkflowInstance
	var total int64
	db := model.DB().Model(&model.WorkflowInstance{}).Where("id in (?) and workflow_instances.deleted = 0", nodeOperatorWorkInstanceIds)
	if req.WorkflowName != "" {
		db = db.Where("workflow_name like ?", "%"+req.WorkflowName+"%")
	}
	if req.Creator != "" {
		db = db.Where("creator like ?", "%"+req.Creator+"%")
	}
	if req.Priority != nil {
		db = db.Where("priority = ?", req.Priority)
	}
	if req.Status != "" {
		db = db.Where("status = ?", req.Status)
	}

	db.Count(&total).Order("priority desc, id asc").Offset(start).Limit(end).Find(&workflowInstances)
	return response.JsonOk(c, map[string]interface{}{"records": workflowInstances, "total": total}, "获取成功")
}

// FindWorkflowInstanceById 根据ID查找工作流实例
func FindWorkflowInstanceById(c *lib.GinContext) error {
	var req *WorkflowInstanceReq
	if err := c.Bind(&req); err != nil {
		c.Logger().Error("参数错误：" + err.Error())
		return response.JsonFail(c, "参数错误")
	}

	var workflowInstance model.WorkflowInstance
	result := model.DB().Where("id = ?", req.Id).First(&workflowInstance)
	if result.Error != nil {
		c.Logger().Error(result.Error.Error())
		return response.JsonFail(c, "未找到工作流实例")
	}

	var nodes []model.Node
	result = model.DB().Where("workflow_instance_id = ?", workflowInstance.Id).Find(&nodes)
	if result.Error != nil {
		c.Logger().Error(result.Error.Error())
		return response.JsonFail(c, "未找到工作流节点")
	}
	return response.JsonOk(c, &WorkflowInstanceRes{
		WorkflowInstance: &workflowInstance,
		Nodes:            nodes,
	})
}

// FindWorkflowInstanceDetailById 根据ID查找工作流实例详情
func FindWorkflowInstanceDetailById(c *lib.GinContext) error {
	var req *WorkflowInstanceReq
	if err := c.Bind(&req); err != nil {
		c.Logger().Error("参数错误：" + err.Error())
		return response.JsonFail(c, "参数错误")
	}

	var workflowInstance model.WorkflowInstance
	result := model.DB().Where("id = ?", req.Id).First(&workflowInstance)
	if result.Error != nil {
		c.Logger().Error(result.Error.Error())
		return response.JsonFail(c, "未找到工作流实例")
	}

	var nodeActionHistories []model.NodeActionHistory
	result = model.DB().Where("workflow_instance_id = ?", workflowInstance.Id).Order("node_id asc,id asc").Find(&nodeActionHistories)
	if result.Error != nil {
		c.Logger().Error(result.Error.Error())
		return response.JsonFail(c, "未找到节点操作记录")
	}

	var currentNode model.Node
	model.DB().Where("id = ?", workflowInstance.CurrentNodeId).First(&currentNode)
	// 判断currentNode状态是否为审核中
	if currentNode.Status == constants.NodeStatusApproving {
		t := constants.NodeActionTypeOrApprove
		if currentNode.ExamineMode == 2 {
			t = constants.NodeActionTypeAndApprove
		}

		// 添加一个当前状态的操作记录
		currentNodeActionHistory := &model.NodeActionHistory{
			WorkflowInstanceId: workflowInstance.Id,
			NodeId:             currentNode.Id,
			NodeName:           currentNode.NodeName,
			NodeType:           currentNode.Type,
			Type:               t,
			ActionInfo:         getAssigneeAndOperatorActionInfoJson(&currentNode),
			Status:             constants.NodeStatusApproving,
			Comment:            "",
		}
		nodeActionHistories = append(nodeActionHistories, *currentNodeActionHistory)
	}

	var subsequentNodes [][]SingleNode
	// 工单状态不在complete、cancel、reject状态下，才需要解析后续节点
	if !slices.Contains([]string{constants.WorkflowInstanceStatusComplete, constants.WorkflowInstanceStatusCancel, constants.WorkflowInstanceStatusReject}, workflowInstance.Status) {
		// 解析出后续可能的节点
		ss, err := parseSubsequentNodes(currentNode, c)
		if err != nil {
			c.Logger().Error(err.Error())
			return response.JsonFail(c, "解析后续节点失败")
		}
		subsequentNodes = ss
	}

	return response.JsonOk(c, &WorkflowInstanceDetailRes{
		WorkflowInstance:    workflowInstance,
		NodeActionHistories: nodeActionHistories,
		SubsequentNodes:     subsequentNodes,
	})
}

// 解析出后续节点
func parseSubsequentNodes(currentNode model.Node, c *lib.GinContext) ([][]SingleNode, error) {
	var childNode *Node
	if currentNode.ChildNode != nil {
		err := json.Unmarshal(currentNode.ChildNode, &childNode)
		if err != nil {
			c.Logger().Error(err.Error())
			return nil, err
		}
	}

	var conditionNodes []*Node
	if currentNode.ConditionNodes != nil {
		err := json.Unmarshal(currentNode.ConditionNodes, &conditionNodes)
		if err != nil {
			c.Logger().Error(err.Error())
			return nil, err
		}
	}

	var parentNodes []*Node
	if currentNode.ParentNodes != nil {
		err := json.Unmarshal(currentNode.ParentNodes, &parentNodes)
		if err != nil {
			c.Logger().Error(err.Error())
			return nil, err
		}
	}

	// 计算所有可能的执行路径
	paths := calculateExecutionPaths(childNode, conditionNodes, parentNodes)
	return paths, nil
}

// calculateExecutionPaths 计算工作流的所有可能执行路径
func calculateExecutionPaths(childNode *Node, conditionNodes []*Node, parentNodes []*Node) [][]SingleNode {
	var allPaths [][]SingleNode

	// 1. 如果有条件节点，每个条件分支都是一条可能的路径
	if len(conditionNodes) > 0 {
		for _, conditionNode := range conditionNodes {
			// 递归获取每个条件节点的所有可能路径
			conditionPaths := buildAllPathsFromNode(conditionNode)

			// 条件节点执行完后，需要执行同级的childNode
			if childNode != nil {
				childPaths := buildAllPathsFromNode(childNode)
				// 合并条件路径和子节点路径的所有组合
				for _, conditionPath := range conditionPaths {
					for _, childPath := range childPaths {
						combinedPath := append(conditionPath, childPath...)
						allPaths = append(allPaths, combinedPath)
					}
				}
			} else {
				allPaths = append(allPaths, conditionPaths...)
			}
		}
	} else if childNode != nil {
		// 2. 如果没有条件节点，只有普通的childNode路径
		childPaths := buildAllPathsFromNode(childNode)
		allPaths = append(allPaths, childPaths...)
	}

	// 3. 如果有父节点，需要与当前路径进行组合计算
	if len(parentNodes) > 0 {
		// 如果当前已有路径，需要与父节点路径进行组合
		if len(allPaths) > 0 {
			var combinedPaths [][]SingleNode
			for _, currentPath := range allPaths {
				for _, parentNode := range parentNodes {
					parentPaths := buildAllPathsFromNode(parentNode)
					for _, parentPath := range parentPaths {
						// 父节点路径 + 当前路径
						combinedPath := append(currentPath, parentPath...)
						combinedPaths = append(combinedPaths, combinedPath)
					}
				}
			}
			allPaths = combinedPaths
		} else {
			// 如果当前没有路径，直接使用父节点路径
			var currentPath []SingleNode
			var combinedPaths [][]SingleNode
			for _, parentNode := range parentNodes {
				parentPaths := buildAllPathsFromNode(parentNode)
				for _, parentPath := range parentPaths {
					// 父节点路径 + 当前路径
					combinedPath := append(currentPath, parentPath...)
					combinedPaths = append(combinedPaths, combinedPath)
				}
			}
			allPaths = combinedPaths
		}
	}

	return allPaths
}

// buildAllPathsFromNode 从指定节点开始构建所有可能的执行路径
func buildAllPathsFromNode(node *Node) [][]SingleNode {
	if node == nil {
		return [][]SingleNode{}
	}

	var allPaths [][]SingleNode

	// 创建当前节点
	currentSingleNode := SingleNode{
		WorkflowInstanceId: node.WorkflowInstanceId,
		NodeName:           node.NodeName,
		Type:               node.Type,
		NodeUserList:       node.NodeUserList,
		ExamineMode:        node.ExamineMode,
		Condition:          node.Condition,
	}

	// 如果当前节点是条件节点，需要处理所有条件分支
	if node.Type == constants.NodeTypeCondition && len(node.ConditionNodes) > 0 {
		// 对于每个条件分支，递归获取所有路径
		for _, conditionNode := range node.ConditionNodes {
			if conditionNode.ChildNode != nil {
				subPaths := buildAllPathsFromNode(conditionNode.ChildNode)
				for _, subPath := range subPaths {
					path := append([]SingleNode{currentSingleNode}, subPath...)
					allPaths = append(allPaths, path)
				}
			} else {
				allPaths = append(allPaths, []SingleNode{currentSingleNode})
			}
		}

		// 条件节点执行完后，还需要执行同级的childNode
		if node.ChildNode != nil {
			childPaths := buildAllPathsFromNode(node.ChildNode)
			// 将条件分支路径与子节点路径组合
			var combinedPaths [][]SingleNode
			for _, conditionPath := range allPaths {
				for _, childPath := range childPaths {
					combinedPath := append(conditionPath, childPath...)
					combinedPaths = append(combinedPaths, combinedPath)
				}
			}
			allPaths = combinedPaths
		}
	} else {
		// 非条件节点，继续处理子节点
		if node.ChildNode != nil {
			subPaths := buildAllPathsFromNode(node.ChildNode)
			for _, subPath := range subPaths {
				path := append([]SingleNode{currentSingleNode}, subPath...)
				allPaths = append(allPaths, path)
			}
		} else {
			// 叶子节点
			allPaths = append(allPaths, []SingleNode{currentSingleNode})
		}
	}

	return allPaths
}

// FindAllInstance 查找所有工作流实例
func FindAllInstance(c *lib.GinContext) error {
	var req *common.PageRequest
	if err := c.Bind(&req); err != nil {
		c.Logger().Error("参数错误：" + err.Error())
		return response.JsonFail(c, "参数错误")
	}

	start, end := lib.Paging(req.Page, req.Size)

	var workflowInstances []model.WorkflowInstance
	var total int64
	model.DB().Model(&model.WorkflowInstance{}).Count(&total).Order("id desc").Offset(start).Limit(end).Find(&workflowInstances)

	return response.JsonOk(c, map[string]interface{}{"records": workflowInstances, "total": total}, "获取成功")
}

// CancelWorkflowInstance 取消工作流实例
func CancelWorkflowInstance(c *lib.GinContext) error {
	req := &WorkflowInstanceReq{}
	err := c.Bind(req)
	if err != nil {
		c.Logger().Error(err.Error())
		return response.JsonFail(c, "参数绑定失败")
	}
	// 查找工作流实例
	var workflowInstance model.WorkflowInstance
	result := model.DB().First(&workflowInstance, "id = ?", req.Id)
	if result.Error != nil {
		c.Logger().Error(result.Error.Error())
		return response.JsonFail(c, "未找到工作流实例")
	}

	if value, ok := c.Get(NeedPermissionJudge); ok {
		if b, okBool := value.(bool); okBool && b {
			token := lib.JwtParse(c)
			if token.UserId != workflowInstance.CreatorId {
				return response.JsonFail(c, "你未创建该工单,没有权限取消")
			}
		}
	}

	// 获取当前node
	var node model.Node
	result = model.DB().First(&node, "workflow_instance_id = ? and id = ?", workflowInstance.Id, workflowInstance.CurrentNodeId)
	if result.Error != nil {
		c.Logger().Error(result.Error.Error())
		return response.JsonFail(c, "未找到当前节点")
	}

	token := lib.JwtParse(c)
	actionInfoJson := getOperatorActionInfoJson(token)
	nodeActionHistory := model.NodeActionHistory{
		WorkflowInstanceId: workflowInstance.Id,
		NodeId:             node.Id,
		NodeName:           node.NodeName,
		NodeType:           node.Type,
		Type:               constants.NodeActionTypeCancel,
		ExamineMode:        node.ExamineMode,
		ActionInfo:         actionInfoJson,
	}

	// 保存nodeActionHistory
	result = model.DBWithToken(token).Create(&nodeActionHistory)
	if result.Error != nil {
		c.Logger().Error(result.Error.Error())
		return response.JsonFail(c, "取消工作流实例失败")
	}

	// 删除nodeAssignee
	result = model.DB().Delete(&model.NodeAssignee{}, "workflow_instance_id = ? and node_id = ?", workflowInstance.Id, node.Id)
	if result.Error != nil {
		c.Logger().Error(result.Error.Error())
		return response.JsonFail(c, "取消工作流实例失败")
	}

	// 更改node状态
	node.Status = constants.NodeStatusCancel
	result = model.DBWithGinContext(c).Model(&model.Node{}).Where("id = ?", node.Id).Updates(map[string]interface{}{
		"status": node.Status,
	})
	if result.Error != nil {
		c.Logger().Error(result.Error.Error())
		return response.JsonFail(c, "取消工作流实例失败")
	}

	// 更改工作流实例状态
	workflowInstance.Status = constants.WorkflowInstanceStatusCancel
	result = model.DBWithGinContext(c).Model(&model.WorkflowInstance{}).Where("id = ?", workflowInstance.Id).Updates(map[string]interface{}{
		"status": workflowInstance.Status,
	})
	if result.Error != nil {
		c.Logger().Error(result.Error.Error())
		return response.JsonFail(c, "取消工作流实例失败")
	}
	return response.JsonOk(c, nil, "取消工作流实例成功")
}
